// 倒计时
import { ref, computed } from 'vue'

/**
 * 定义一个类型CurrentTime
 */
type CurrentTime = {
  /**
   * 天
   */
  days: number

  /**
   * 小时
   */
  hours: number

  /**
   * 分钟
   */
  minutes: number

  /**
   * 秒
   */
  seconds: number

  /**
   * 毫秒
   */
  milliseconds: number

  /**
   * 总时间
   */
  total: number
}

/**
 * 倒计时配置
 */
type CountDownOptions = {
  /**
   * 倒计时时间
   */
  time: number

  /**
   * 是否显示毫秒
   * 默认：false
   */
  millisecond?: boolean

  /**
   * 倒计时结束回调
   */
  onChange?: (current: CurrentTime) => void

  /**
   * 倒计时结束回调
   */
  onFinish?: () => void
}

const SECOND = 1000,
  MINUTE = 60 * SECOND,
  HOUR = 60 * MINUTE,
  DAY = 24 * HOUR

/**
 * 定义一个函数，用于将时间戳转换为天、小时、分钟、秒、毫秒
 * @param time 时间
 * @returns
 */
const parseTime = (time: number) => {
  // 计算天数
  const days = Math.floor(time / DAY),
    // 计算小时数
    hours = Math.floor((time % DAY) / HOUR),
    // 计算分钟数
    minutes = Math.floor((time % HOUR) / MINUTE),
    // 计算秒数
    seconds = Math.floor((time % MINUTE) / SECOND),
    // 计算毫秒数
    milliseconds = Math.floor(time % SECOND)
  // 返回一个对象，包含天、小时、分钟、秒、毫秒和总时间
  return {
    days,
    hours,
    minutes,
    seconds,
    milliseconds,
    total: time
  }
}

/**
 * 判断两个时间戳是否在同一秒
 * @param t1 时间戳1
 * @param t2 时间戳2
 * @returns boolean
 */
const isSameSecond = (t1: number, t2: number) => Math.floor(t1 / SECOND) === Math.floor(t2 / SECOND)

/**
 * 导出一个函数，用于倒计时
 * @param options 倒计时选项
 * @returns
 */
export function useCountDwon(options: CountDownOptions) {
  // 定义倒计时结束时间、是否正在倒计时、动画帧ID
  let endTime: number, counting: boolean, reqId: number
  // 定义倒计时剩余时间，初始值为传入的options.time
  const remin = ref(options.time)
  // 定义当前倒计时时间，通过parseTime函数解析remin.value
  const current = computed(() => parseTime(remin.value))
  // 获取当前倒计时剩余时间
  const getCurrentRemin = () => Math.max(endTime - Date.now(), 0)

  // 暂停倒计时
  const pause = () => {
    counting = false
    cancelAnimationFrame(reqId)
  }
  // 设置倒计时剩余时间
  const setRemin = (value: number) => {
    remin.value = value
    options?.onChange?.(current.value)
    if (value === 0) {
      pause()
      options.onFinish?.()
    }
  }

  // 微秒级倒计时
  const microTick = () => {
    reqId = requestAnimationFrame(() => {
      if (counting) {
        const reminRemin = getCurrentRemin()
        setRemin(reminRemin)
        if (remin.value > 0) {
          microTick()
        }
      }
    })
  }

  // 宏秒级倒计时
  const macroTick = () => {
    reqId = requestAnimationFrame(() => {
      if (counting) {
        const reminRemin = getCurrentRemin()
        if (!isSameSecond(reminRemin, remin.value) || reminRemin === 0) {
          setRemin(reminRemin)
        }
        if (remin.value > 0) {
          macroTick()
        }
      }
    })
  }

  // 开始倒计时
  const tick = () => {
    if (options.millisecond) {
      microTick()
    } else {
      macroTick()
    }
  }

  // 开始倒计时
  const start = () => {
    if (!counting) {
      endTime = Date.now() - remin.value
      counting = false
      tick()
    }
  }

  // 重置倒计时
  const reset = (total = options.time) => {
    pause()
    remin.value = total
  }

  // 返回倒计时函数
  return {
    start,
    pause,
    reset,
    current
  }
}
